//-----------------------------------------------------------------------------
//	File: rotenc.c
//	Author: hsia
//		bsp of rotary encoder
//-----------------------------------------------------------------------------

#include "rotenc.h"

// rotary gpio configration
#define ROTENC_RCC_ALL		RCC_APB2Periph_GPIOA
#define	ROTENC_A_PORT		GPIOA
#define	ROTENC_A_PIN		GPIO_Pin_6
#define	ROTENC_B_PORT		GPIOA
#define	ROTENC_B_PIN		GPIO_Pin_5
#define	ROTENC_S_PORT		GPIOA
#define	ROTENC_S_PIN		GPIO_Pin_4

// key
#define KEY_SHORT_TIMES		5
#define KEY_LONG_TIMES		500

// in pin shortcut
#define ROTENC_A_IN			((ROTENC_A_PORT->IDR & ROTENC_A_PIN) ? 1u : 0u)
#define ROTENC_B_IN			((ROTENC_B_PORT->IDR & ROTENC_B_PIN) ? 1u : 0u)
#define ROTENC_S_IN			((ROTENC_S_PORT->IDR & ROTENC_S_PIN) ? 0u : 1u)

//-----------------------------------------------------------------------------
//	configure_rotenc_gpio - configure the rotary encoder gpio
//-----------------------------------------------------------------------------
void configure_rotenc_gpio(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	// enable the peripheral clock
	RCC_APB2PeriphClockCmd(ROTENC_RCC_ALL, ENABLE);
	// gpio mode
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	// retenc pin seting
	GPIO_InitStructure.GPIO_Pin = ROTENC_A_PIN;
	GPIO_Init(ROTENC_A_PORT, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = ROTENC_B_PIN;
	GPIO_Init(ROTENC_B_PORT, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = ROTENC_S_PIN;
	GPIO_Init(ROTENC_S_PORT, &GPIO_InitStructure);
}

//-----------------------------------------------------------------------------
//	rotenc_key_scan - scan rotary key
//		@ret: 0=none, 1=short, 2=long
//-----------------------------------------------------------------------------
uint8_t rotenc_key_scan(void)
{
	uint8_t value = 0;
	static uint16_t times = 0;

	if (ROTENC_S_IN) {
		if (times != (KEY_LONG_TIMES+1)) {
			times++;
		}
		if (times == KEY_LONG_TIMES) {
			value = 2;
		}
		else {
			value = 0;
		}
	}
	else {
		if (times < KEY_SHORT_TIMES) {
			value = 0;
		}
		else if (times < KEY_LONG_TIMES) {
			value = 1;
		}
		else {
			value = 0;
		}
		times = 0;
	}

	return value;
}

//-----------------------------------------------------------------------------
//	rotenc_scan - scan the rotary encoder and return value
//		@ret: 0x00=none, 0x01=add, 0xFF=sub
//-----------------------------------------------------------------------------
uint8_t rotenc_scan(void)
{
	uint8_t ret = 0;
	uint8_t temp = 0;
	static uint8_t state;

	temp = ROTENC_B_IN;
	temp |= ROTENC_A_IN << 1;
	if ((state & 0x03) != temp) {
		state <<= 2;
		state |= temp;
		switch (state & 0x3F) {
			//case 18:
			case 52:
				ret = 0x01; break;
			//case 33:
			case 7:
				ret = 0xFF; break;
			default: break;
		}
	}

	return ret;
}

/*
//-----------------------------------------------------------------------------
//	example
//-----------------------------------------------------------------------------
{
	static uint8_t rotval;
	static uint8_t keyval;

	configure_rotenc_gpio();
	rotval = rotenc_scan();
	keyval = rotenc_key_scan();

	switch (rotval) {
		case 0x01: // add
			break;
		case 0xFF: // sub
			break;
	}

	switch (keyval) {
		case 0x01: // short
			break;
		case 0x02: // long
			break;
	}
}
*/
